home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / LDB171.ARJ / MUTUAL.CPP < prev    next >
C/C++ Source or Header  |  1992-05-12  |  12KB  |  565 lines

  1. /*
  2.     mutual.cpp -- Loose Data Binder v 1.7:
  3.         mutually owned and persistence
  4.  
  5.     (C) Copyright 1992  John W. Small
  6.     All rights reserved
  7.  
  8.     PSW / Power SoftWare
  9.     P.O. Box 10072
  10.     McLean, Virginia 22102 8072 USA
  11.     (703) 759-3838
  12. */
  13.  
  14.  
  15. #ifndef Mutual_HPP
  16. #include "mutual.hpp"
  17. #endif
  18.  
  19.  
  20.  
  21. /**  Mutual Class  **/
  22.  
  23.  
  24. Mutual::Mutual(initMutual)
  25. {
  26.     parenT = voiD0;
  27.     refCount = streamCount = 0U;
  28.     streamPos = 0L;
  29. }
  30.  
  31. void Mutual::serror(const char *msg, unsigned id)
  32. {
  33.     if (streamDebug)
  34.         cerr << endl
  35.             << "Class id: " << setw(6) << id
  36.             <<  "   stream error - "
  37.             << msg << endl;
  38. }
  39.  
  40. void Mutual::error(const char *msg)
  41. {
  42.     if (streamDebug)
  43.         cerr << endl
  44.             <<"Class id: " << setw(6) << ID()
  45.             << "    &instance:   "
  46.             << (void *) this << endl
  47.             <<  "Stream error - "
  48.             << msg << endl;
  49. }
  50.  
  51. void Mutual::warn(const char *msg)
  52. {
  53.     if (streamDebug)
  54.         cerr << endl
  55.             << "Class id: " << setw(6) << ID()
  56.             << "    &instance:   "
  57.             << (void *) this << endl
  58.             <<  "Stream warning - "
  59.             << msg << endl;
  60. }
  61.  
  62. int  Mutual::refDebug = 0;
  63. int  Mutual::streamDebug = 0;
  64. char Mutual::memberTermChar = '\n';
  65.  
  66. void Mutual::RegisterClass(unsigned id,
  67.     MutuaL (*fgeT)(istream&, MutuaL))
  68. {
  69.     StreamReg.RegisterClass(id,fgeT);
  70. }
  71.  
  72. unsigned Mutual::restream()
  73. {
  74.     unsigned underFlow = (streamPos? 
  75.         refCount - streamCount : 0);
  76.     
  77.     streamCount = 0; 
  78.     streamPos = 0L;
  79.     if (underFlow)
  80.         warn("restream: streamed less than "
  81.             "referenced");    
  82.     return underFlow;
  83. }
  84.  
  85. void Mutual::unlink(voiD P)
  86. {
  87.     if (refDebug)
  88.         if (refCount)
  89.             cerr << endl
  90.             << "Class id: " << setw(6) << ID()
  91.             << "    &instance:   "
  92.             << (void *) this << endl
  93.             <<  "Unlinking, starting refCount: "
  94.             << refCount << endl;
  95.         else
  96.             cerr << endl
  97.             << "Class id: " << setw(6) << ID()
  98.             << "    &instance:   "
  99.             << (void *) this << endl
  100.             <<  "unlink() underflow" << endl;
  101.     if (refCount)
  102.         --refCount;
  103.     if (parenT == P || !refCount)
  104.         parenT = voiD0;
  105. }
  106.  
  107. int Mutual::link(voiD P)
  108. {
  109.     if (refCount >= UINT_MAX)  {
  110.         if (refDebug)
  111.             cerr << endl
  112.             << "Class id: " << setw(6) << ID()
  113.             << "    &instance:   "
  114.             << (void *) this << endl
  115.             <<  "link() overflow" << endl;
  116.         return 0;
  117.     }
  118.     refCount++;
  119.     if (!parenT && P)
  120.         parenT = P;
  121.     if (refDebug)
  122.         cerr << endl
  123.             << "Class id: " << setw(6) << ID()
  124.             << "    &instance:   "
  125.             << (void *) this << endl
  126.             <<  "Adding link, new refCount: "
  127.             << refCount << endl;
  128.     return 1;
  129. }
  130.  
  131.  
  132.  
  133. /**  MBinder Class  **/
  134.  
  135.  
  136. voiD MBinder::Dassign(voiD D, const voiD S)
  137. {
  138.     // invokes Mutual's overloaded operator=()
  139.     if ((*(MutuaL)D) = (*(MutuaL)S))
  140.         return D;
  141.     return voiD0;
  142. }
  143.  
  144. voiD MBinder::Dnew(const voiD D)
  145. {
  146.     // invokes Mutual's copy initializer constructor
  147.     return  (voiD) ((MutuaL)D)->clone();
  148. }
  149.  
  150. void MBinder::Ddelete(voiD D)
  151. {
  152.     // invokes Mutual's destructor
  153.     if (!((MutuaL)D)->RefCount())
  154.         delete (MutuaL) D;
  155. }
  156.  
  157. void MBinder::Dstore(ostream& os, voiD D)
  158. {
  159.     // invokes operator<<(ostream&,Mutual&)
  160.     os << *(MutuaL)D;
  161. }
  162.  
  163. voiD MBinder::Dload(istream& is)
  164. {
  165.     MutuaL M;
  166.  
  167.     // invokes operator>>(istream&,MutuaL&)
  168.     is >> M;
  169.     return (voiD) M;
  170. }
  171.  
  172. MBindeR MBinder::load(istream& is, MBindeR thiS)
  173. {
  174.     int newed;
  175.  
  176.     if (thiS)
  177.         newed = 0;
  178.     else  {
  179.         if ((thiS = new MBinder(initVFTsOnly))
  180.             == MBindeR0)  {
  181.             sberror("unable to construct "
  182.                 "new MBinder for "
  183.                 "loading");
  184.             return MBindeR0;
  185.         }
  186.         newed = 1;
  187.     }
  188.     if (!Binder::load(is,(BindeR)thiS))  {
  189.         if (newed)
  190.             delete (voiD) thiS;
  191.         return MBindeR0;
  192.     }
  193.     return thiS;
  194. }
  195.  
  196. unsigned MBinder::restream()
  197. {
  198.     MutuaL M;
  199.     unsigned result = Mutual::restream();
  200.  
  201.     for (unsigned i = 0;
  202.         (M = (MutuaL) atGet(i)) != MutuaL0;
  203.         i++)
  204.         M->restream();
  205.     return result;
  206. }
  207.  
  208.  
  209.  
  210. /**  StreamRegistry Class, etc.  **/
  211.  
  212.  
  213. struct StreamClassRecord  {
  214.     unsigned id;
  215.     MutuaL (*fgeT)(istream&, MutuaL);
  216.     StreamClassRecord(unsigned id,
  217.         MutuaL (*fgeT)(istream&, MutuaL))
  218.         { this->id = id; this->fgeT = fgeT; }
  219.     ~StreamClassRecord()  {}
  220. };
  221.  
  222. typedef struct StreamClassRecord * SCRecorD;
  223. #define SCRecorD0  ((SCRecorD)0)
  224.  
  225.  
  226. struct StreamInstanceRecord  {
  227.     MutuaL InstancE;
  228.     unsigned refCount, streamCount;
  229.     long streamPos;
  230.     StreamInstanceRecord(MutuaL InstancE,
  231.         unsigned refCount, long streamPos)
  232.     {
  233.         this->InstancE = InstancE;
  234.         this->refCount = refCount;
  235.         streamCount = 1;
  236.         this->streamPos = streamPos;
  237.     }
  238.     ~StreamInstanceRecord()  {}
  239. };
  240.  
  241. typedef struct StreamInstanceRecord * SIRecorD;
  242. #define SIRecorD0  ((SIRecorD)0)
  243.  
  244.  
  245. struct StreamFunctionRecord  {
  246.     unsigned id;
  247.     GenericFnC fnC;
  248.     StreamFunctionRecord(unsigned id,
  249.         GenericFnC fnC)
  250.         { this->id = id; this->fnC = fnC; }
  251.     ~StreamFunctionRecord()  {}
  252. };
  253.  
  254. typedef struct StreamFunctionRecord * SFRecorD;
  255. #define SFRecorD0  ((SFRecorD)0)
  256.  
  257.  
  258. void StreamRegistry::CIerror(char *msg, unsigned id,
  259.     MutuaL InstancE)
  260. {
  261.     if (debug)
  262.         cerr << endl
  263.             << "Class id: " << setw(6) << id
  264.             << "    &instance:   "
  265.             << (void *) InstancE << endl
  266.             << "Class Registry error - "
  267.             << msg << endl;
  268. }
  269.  
  270. void StreamRegistry::CIwarn(char *msg, unsigned id,
  271.     MutuaL InstancE)
  272. {
  273.     if (debug)
  274.         cerr << endl
  275.             << "Class id: " << setw(6) << id
  276.             << "    &instance:   "
  277.             << (void *) InstancE << endl
  278.             << "Class Registry warning - "
  279.             << msg << endl;
  280. }
  281.  
  282. void StreamRegistry::FNCerror(char *msg, unsigned id)
  283. {
  284.     if (debug)
  285.         cerr << endl
  286.             << "Function id: " << setw(6)
  287.             << id << endl
  288.             << "Function Registry error - "
  289.             << msg << endl;
  290. }
  291.  
  292. void StreamRegistry::FNCwarn(char *msg, unsigned id)
  293. {
  294.     if (debug)
  295.         cerr << endl
  296.             << "Function id: " << setw(6)
  297.             << id << endl
  298.             << "Function Registry warning - "
  299.             << msg << endl;
  300. }
  301.  
  302. int StreamRegistry::debug = 0;
  303.  
  304. unsigned StreamRegistry::restream()
  305. {
  306.  
  307.     unsigned underFlow = InstanceRecords.Nodes();
  308.     SIRecorD R;
  309.  
  310.     for (unsigned i = 0; i < underFlow; i++)  {
  311.         R = (SIRecorD) InstanceRecords.atGet(i);
  312.         CIwarn("Restream: holding pen under-linked",
  313.             R->InstancE->ID(),R->InstancE);
  314.     }
  315.     InstanceRecords.allDel();
  316.     return underFlow;
  317. }
  318.  
  319. void StreamRegistry::RegisterClass(unsigned id,
  320.     MutuaL (*fgeT) (istream&, MutuaL))
  321. {
  322.     unsigned i;
  323.  
  324.     for (i = 0; i < ClassRecords.Nodes(); i++)
  325.         if (((SCRecorD)ClassRecords[i])->id
  326.             == id)
  327.             break;
  328.     if (i < ClassRecords.Nodes())
  329.         if (((SCRecorD)ClassRecords[i])->fgeT
  330.             == fgeT)  {
  331.             CIwarn("multiple registration of"
  332.                 " loader",id);
  333.             return;
  334.         }
  335.         else  {
  336.             CIerror("id conflict",id);
  337.             return;
  338.         }
  339.     SCRecorD R = new StreamClassRecord(id,fgeT);
  340.     if (!R)
  341.         CIerror("class record memory exhausted",
  342.             id);
  343.     else if (!ClassRecords.insQ((voiD)R))  {
  344.         CIerror("class record can't be queued",
  345.             id);
  346.         delete R;
  347.     }
  348. }
  349.  
  350. void StreamRegistry::registerFunction(unsigned id,
  351.     GenericFnC fnC)
  352. {
  353.     unsigned i;
  354.  
  355.     for (i = 0; i < FunctionRecords.Nodes(); i++)
  356.         if (((SFRecorD)FunctionRecords[i])->id
  357.             == id) break;
  358.     if (i < FunctionRecords.Nodes())
  359.         if (((SFRecorD)FunctionRecords[i])->fnC
  360.             == fnC)
  361.         {
  362.             FNCwarn("attempted multiple"
  363.                 " registration"
  364.                 " of function",
  365.                 id);
  366.             return;
  367.         }
  368.         else {
  369.             FNCerror("id conflict",id);
  370.             return;
  371.         }
  372.     SFRecorD R = new StreamFunctionRecord(id,fnC);
  373.     if (!R)
  374.         FNCerror("fnC memory exhausted",id);
  375.     else if (!FunctionRecords.insQ((voiD)R))  {
  376.         FNCerror("fnC record can't be queued",
  377.             id);
  378.         delete R;
  379.     }
  380. }
  381.  
  382. GenericFnC StreamRegistry::fnCLU(unsigned id)
  383. {
  384.     unsigned i;
  385.  
  386.     for (i = 0; i < FunctionRecords.Nodes(); i++)
  387.         if (((SFRecorD)FunctionRecords[i])->id
  388.             == id) break;
  389.     if (i >= FunctionRecords.Nodes())  {
  390.         FNCerror("unknown function",id);
  391.         return GenericFnC0;
  392.     }
  393.     else
  394.         return ((SFRecorD)FunctionRecords[i])->fnC;
  395. }
  396.  
  397. unsigned StreamRegistry::fnCID(GenericFnC fnC)
  398. {
  399.     unsigned i;
  400.  
  401.     for (i = 0; i < FunctionRecords.Nodes(); i++)
  402.         if (((SFRecorD)FunctionRecords[i])->fnC
  403.             == fnC)
  404.             break;
  405.     if (i >= FunctionRecords.Nodes())  {
  406.         FNCerror("unknown function",
  407.             ID_UnknownGenericFnC);
  408.         return ID_UnknownGenericFnC;
  409.     }
  410.     else
  411.         return ((SFRecorD)FunctionRecords[i])->id;
  412. }
  413.  
  414. void StreamRegistry::forgetRegistrations()
  415. {
  416.     ClassRecords.allDel();
  417.     InstanceRecords.allDel();
  418.     FunctionRecords.allDel();
  419. }
  420.  
  421. void StreamRegistry::fput(ostream& os, Mutual& Instance)
  422. {
  423.     unsigned id, i;
  424.     long streamPos;
  425.  
  426.     id = Instance.ID();
  427.     for (i = 0; i < ClassRecords.Nodes(); i++)
  428.         if (((SCRecorD)ClassRecords[i])->id == id)
  429.             break;
  430.     if (i >= ClassRecords.Nodes())  {
  431.         CIerror("attempted store of unknown class",
  432.             id);
  433.     }
  434.     else if (Instance.refCount <= Instance.streamCount)
  435.         CIerror("more stores attempted than links",
  436.             id,&Instance);
  437.     else {
  438.         Instance.streamCount++;
  439.         if (Instance.streamPos)  {
  440.               // already stored!
  441.             if (!(os << ID_MRef << Mendm
  442.                 << Instance.streamPos
  443.                 << Mendm))
  444.                 CIerror("unable to store "
  445.                     "multiple reference",
  446.                     id,&Instance);
  447.         }
  448.         else  { // Never store object at streamPos 0
  449.             if ((streamPos = os.tellp()) == 0)
  450.                 if (!(os << ID_MRef << Mendm))
  451.                     CIerror("unable to skip "
  452.                         "streamPos 0");
  453.                 else
  454.                     streamPos = os.tellp();
  455.             if (!(os << id << Mendm))
  456.                 CIerror("unable to store id",
  457.                     id,&Instance);
  458.             else  {
  459.                 Instance.streamPos = streamPos;
  460.                 if (!(os << Instance.refCount
  461.                     << Mendm))
  462.                     CIerror("unable to store "
  463.                         "refCount ",id,
  464.                         &Instance);
  465.                 else
  466.                     Instance.fput(os);
  467.             }
  468.         }
  469.     }
  470.     os << flush;
  471. }
  472.  
  473. void StreamRegistry::fget(istream& is, MutuaL& InstancE)
  474. {
  475.     unsigned id, refCount, i;
  476.     long streamPos;
  477.     SIRecorD R;
  478.  
  479.     InstancE = MutuaL0;
  480.     if ((streamPos = is.tellg()) == 0)
  481.         if (!(is >> id >> Mnextm))  {
  482.             CIerror("unable to strip skip 0");
  483.             return;
  484.         }
  485.         else
  486.             streamPos = is.tellg();
  487.     if (!(is >> id >> Mnextm))  {
  488.         CIerror("unable to read id");
  489.         return;
  490.     }
  491.     if (id == ID_MRef)  {
  492.         // link to previously loaded Instance
  493.         if (!(is >> streamPos >> Mnextm))  {
  494.             CIerror("unable to read streamPos");
  495.             return;
  496.         }
  497.         for (i = 0; i < InstanceRecords.Nodes(); i++)
  498.             if ((R = (SIRecorD)InstanceRecords[i])
  499.                 ->streamPos == streamPos)  {
  500.                 // found saved instance!
  501.                 InstancE = R->InstancE;
  502.                 if (R->refCount <= ++R->streamCount)
  503.                     // discard when done!
  504.                     InstanceRecords.atRmv(i);
  505.                 break;
  506.             }
  507.         if (!InstancE)
  508.             CIerror("unable to establish link to"
  509.                 " previously loaded class",
  510.                 id);
  511.     }
  512.     else  {  // load instance
  513.         if (!(is >> refCount >> Mnextm))  {
  514.             CIerror("unable to read refCount",id);
  515.             return;
  516.         }
  517.         for (i = 0; i < ClassRecords.Nodes(); i++)
  518.             if (((SCRecorD)ClassRecords[i])->id
  519.                 == id)
  520.                 break;
  521.         if (i >= ClassRecords.Nodes())  {
  522.             CIerror("attempted load of unknown "
  523.                 "class",id);
  524.             return;
  525.         }
  526.         if ((InstancE = (*((SCRecorD)
  527.             ClassRecords[i])->fgeT)
  528.             (is,MutuaL0)) == MutuaL0)
  529.         {
  530.             CIerror("unable to load instance",id);
  531.             return;
  532.         }
  533.         if (refCount > 1)  {
  534.             // 1st of many - save in holding pen
  535.             R = new StreamInstanceRecord
  536.                 (InstancE,refCount,streamPos);
  537.             if (!R)
  538.                 CIerror("instance holding record"
  539.                 " memory exhausted",
  540.                 id,InstancE);
  541.             else if (!InstanceRecords.insQ
  542.                 ((voiD)R))  {
  543.                 CIerror("unable to hold "
  544.                     "instance for "
  545.                     "multiple links",
  546.                     id,InstancE);
  547.                 delete R;
  548.             }
  549.         }
  550.     }
  551. }
  552.  
  553. StreamRegistry StreamReg;
  554.  
  555. ostream& Mendm(ostream& os)
  556. {
  557.     return os << Mutual::memberTermChar << flush;
  558. }
  559.  
  560. istream& Mnextm(istream& is)
  561. {
  562.     is.get();
  563.     return is;
  564. }
  565.